#include "fig_enemy_manager.h"
#include "fig_enemy_collection.h"
#include "fig_enemybullet_Master.h"

#include "num/rand.h"
#include "lang/lang.h"
#include "util/mmgr.h"		    // Needs to come in early
#include "util/common_macros.h"		// macros
#include "util/log.h"		    // logging
#include "util/timer.h"		    // logging

FIGEnemyManager::FIGEnemyManager()
{

}



FIGEnemyManager&		FIGEnemyManager::Instance()
{
	static FIGEnemyManager Inst;
	return Inst;
}


void		FIGEnemyManager::RenderDecal(const math::Vec2& Offset,float Scale)
{
	for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
	{
		FIGEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		pEnemyCollecction->RenderDecal(Offset,Scale); 
	}
}

void		FIGEnemyManager::Render(const math::Vec2& Offset,float Scale)
{
    
	for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
	{
		FIGEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		pEnemyCollecction->Render(Offset,Scale); 		
	} 
	
}

void		FIGEnemyManager::RenderShadow(const math::Vec2& Offset,float Scale)
{
	for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
	{
		FIGEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		pEnemyCollecction->RenderShadow(Offset,Scale);
	}

	
}

void		FIGEnemyManager::RenderDebug(const math::Vec2& Offset,float Scale)
{
	for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
	{
		FIGEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		pEnemyCollecction->RenderDebug(Offset,Scale);
	}

	FIGEnemyBulletMaster::Instance().RenderDebug(Offset, Scale);
}


void		FIGEnemyManager::Tick(float dt)
{
	for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
	{
		FIGEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		pEnemyCollecction->Tick(dt);
	}

}


void		FIGEnemyManager::Clear()
{
	for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
	{
		FIGEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		pEnemyCollecction->Clear();
	}

	for( int i = (int)m_EnemyCollections.size() - 1; i >= 0; i--)
	{
		FIGEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		UTIL_SAFE_DELETE(pEnemyCollecction);
	}
	m_EnemyCollections.resize(0);
}


void		FIGEnemyManager::Spawn(const FIGLevel::EnemyInfo* pEnemyInfo , bool bUniqe )
{
	
	bool Found = false;
	for( int i = (int)m_EnemyCollections.size()- 1 ; i >= 0 ; i--)
	{
		FIGEnemyCollection* pEnemyCollection = m_EnemyCollections[i];
		if ( ((int)(pEnemyCollection->GetType())) == pEnemyInfo->EnemyTypeEnumInt
			&& 
			pEnemyCollection->GetNameCRC() == pEnemyInfo->NameCRC
			)
		{
			if(!bUniqe)
				pEnemyCollection->Spawn(pEnemyInfo);
			
			i = -1;
			Found = true;
		}		
	}

	if(!Found)
	{
		FIGEnemyCollection* pEnemyCollection = new FIGEnemyCollection(
												((FIGEnemyCraft::ENEMY_TYPES)(pEnemyInfo->EnemyTypeEnumInt)),
													pEnemyInfo->NameCRC
													);
		m_EnemyCollections.push_back(pEnemyCollection);
		pEnemyCollection->Spawn(pEnemyInfo);
	}
}


int			FIGEnemyManager::GetCount()const
{
	int TotalCount = 0;
	for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
	{
		FIGEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		TotalCount += pEnemyCollecction->GetCount();
	}

	return TotalCount;
	
}



bool		FIGEnemyManager::HitTest(FIGBullet* pBullet)
{
	for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
	{
		FIGEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		if(pEnemyCollecction->HitTest(pBullet))
			return true;
	}

	return false;
}

FIGCraft*			FIGEnemyManager::GetTopidoTarget(FIGBullet* pBullet)
{
	std::vector<FIGCraft*> pCrafts;	
	FIGCraft* pReturnCraft = NULL;
		

	for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
	{
		FIGEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		
		for( int j = 0; j < pEnemyCollecction->GetCount(); j++)
		{
			FIGCraft* pCraft = pEnemyCollecction->GetAirCraftByIndex(j);
		
			if(pCraft->IsAlive() && pCraft->IsInSideScreen() )
			{
				pCrafts.push_back(pCraft);
			}
		}
	}
	if(pCrafts.size() > 0)
	{
		int Index = num::RAND32::Instance().RandInt(0,pCrafts.size()-1);
		pReturnCraft = pCrafts[Index];		
	}

	pCrafts.resize(0);
	return pReturnCraft;

}


void	FIGEnemyManager::DoDamangeToAll(float DamageAmount)
{
	for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
	{
		FIGEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		
		for( int j = 0; j < pEnemyCollecction->GetCount(); j++)
		{
			FIGCraft* pCraft = pEnemyCollecction->GetAirCraftByIndex(j);
		
			if(pCraft->IsAlive() && pCraft->IsInSideScreen() )
			{
				pCraft->GotDamage(DamageAmount,NULL, true);
			}
		}
	}
}

FIGLifeObj*		FIGEnemyManager::HitTest_Laser(	const math::Vec2& StartPos, 
															float Width,
															math::Vec2& HitPos
															)
{
	
	math::Vec2 HitTestPos = StartPos;

	while(HitTestPos.y > 0)
	{
		for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
		{
			FIGEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
			
			for( int j = 0; j < pEnemyCollecction->GetCount(); j++)
			{
				FIGCraft* pCraft = pEnemyCollecction->GetAirCraftByIndex(j);
			
				if(pCraft->IsAlive() && pCraft->IsInSideScreen() )
				{
					HitPos = HitTestPos;
					if(pCraft->HitTest(HitTestPos))					
						return pCraft;				

				}
			}
		}
		HitTestPos.y -= Width;
	}

	return NULL ;
}

void	FIGEnemyManager::ForceKillAll()
{
	for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
	{
		FIGEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		
		for( int j = 0; j < pEnemyCollecction->GetCount(); j++)
		{
			FIGCraft* pCraft = pEnemyCollecction->GetAirCraftByIndex(j);		
			pCraft->ForceKill();
		}
	}	
}
